#include "stdafx.h"
#include "FunctionDispatch.h"

CFunctionDispatch::CFunctionDispatch(IWebBrowser2* pBrowser) 
	: m_pBrowser(pBrowser)
	, m_pParam(NULL)
{
}

void CFunctionDispatch::SetParam(void* pParam)
{
	m_pParam = pParam;
}

void CFunctionDispatch::RegFun( LPCTSTR lpszFunName, TypeFunDispatch fun )
{
	m_lsFuns.insert(TypeFunDispatchMap::value_type(lpszFunName, fun));
}

STDMETHODIMP CFunctionDispatch::GetIDsOfNames( REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid )
{
	TypeFunDispatchMap::iterator it = m_lsFuns.find(*rgszNames);
	if (it != m_lsFuns.end())
	{
		*rgdispid = (long)(*it).second;
		return S_OK;
	}
	
	return E_FAIL;
}

STDMETHODIMP CFunctionDispatch::Invoke( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr )
{
	TypeFunDispatch fun = (TypeFunDispatch)dispidMember;
	if (fun)
	{
		_variant_t vRet;
		if (DISPATCH_PROPERTYGET == wFlags)
		{
			vRet = new CMethodDispatch(m_pBrowser, this, fun, m_pParam);
		}
		else
		{
			if (pdispparams->cArgs == 1 && pdispparams->rgvarg[0].vt == VT_DISPATCH)
			{
				vRet = fun(m_pBrowser, pdispparams->rgvarg[0].pdispVal, m_pParam);
			}
			else
			{
				vRet = fun(m_pBrowser, NULL, m_pParam);
			}
		}
		
		if (pvarResult)
			VariantCopy(pvarResult, &vRet);
		return S_OK;
	}
	return E_FAIL;
}

CMethodDispatch::CMethodDispatch(IWebBrowser2* pBrowser, 
								 IDispatch* pFunctionDispatch, 
								 TypeFunDispatch pMethod, 
								 void* pParam )
	: m_pBrowser(pBrowser)
	, m_spFunctionDispatch(pFunctionDispatch)
	, m_fun(pMethod)
	, m_pParam(pParam)
{
}

STDMETHODIMP CMethodDispatch::GetIDsOfNames( REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid )
{
	*rgdispid = NULL;
	return S_OK;
}

STDMETHODIMP CMethodDispatch::Invoke( DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr )
{
	_variant_t vRet;
	if (pdispparams->cArgs == 1 && pdispparams->rgvarg[0].vt == VT_DISPATCH)
	{
		vRet = m_fun(m_pBrowser, pdispparams->rgvarg[0].pdispVal, m_pParam);
	}
	else
	{
		vRet = m_fun(m_pBrowser, NULL, m_pParam);
	}
	if (pvarResult)
		VariantCopy(pvarResult, &vRet);
	return S_OK;
}